package cz.vutbr.feec.utko.ef.examples.regression;

import cz.vutbr.feec.utko.ef.core.Config;
import cz.vutbr.feec.utko.ef.core.GProgram;
import cz.vutbr.feec.utko.ef.evolution.DefaultEvolutionSpecifierTree;
import cz.vutbr.feec.utko.ef.evolution.DisplayType;
import cz.vutbr.feec.utko.ef.evolution.IEvolutionSpecifier;
import cz.vutbr.feec.utko.ef.gp.tree.TreeChromozome;
import cz.vutbr.feec.utko.ef.grammar.Grammar;
import cz.vutbr.feec.utko.ef.grammar.Rule;
import cz.vutbr.feec.utko.ef.individuals.ActionTree;


/**
 * The Class RegressionTest.
 */
public class RegressionTest {

	/**
	 * The main method.
	 * 
	 * @param args the arguments
	 */
	public static void main(String[] args) {
				
		Grammar g = new Grammar();
		
		g.addRule("ROOT", new Rule("E"));
		
		g.addRule("E",
				// E -> E + E
				new Rule(new PlusAction(), "E", "E"),
				// E -> E - E
				new Rule(new MinusAction(), "E", "E"),
				// E -> E * E
				new Rule(new TimesAction(), "E", "E"),
				// E -> E / E
				new Rule(new DivisionAction(), "E", "E"),
				// E -> cislo
				new Rule("INPUT_R1"),
				// E -> cislo
				new Rule("INPUT_R2"),
				// E -> cislo
				new Rule("INPUT_I1"),
				// E -> cislo
				new Rule("INPUT_I2"));
		

		ActionTree R1 = new ReadNumber();
		g.addRule("INPUT_R1", new Rule(R1));
		g.registerInputParameter(R1);
		
		ActionTree R2 = new ReadNumber();
		g.addRule("INPUT_R2", new Rule(R2));
		g.registerInputParameter(R2);
		
		ActionTree I1 = new ReadNumber();
		g.addRule("INPUT_I1", new Rule(I1));
		g.registerInputParameter(I1);
		
		ActionTree I2 = new ReadNumber();
		g.addRule("INPUT_I2", new Rule(I2));
		g.registerInputParameter(I2);
				
		//Training set
		
		double[][] hodnoty = new double[12][5];
		
		hodnoty[0][0] = 40.0;
		hodnoty[0][1] = 10.0;
		hodnoty[0][2] = 0.250;
		hodnoty[0][3] = 1.000;
		hodnoty[0][4] = 8.000;
		
		hodnoty[1][0] = 5.0;
		hodnoty[1][1] = 5.0;
		hodnoty[1][2] = 2.000;
		hodnoty[1][3] = 2.000;
		hodnoty[1][4] = 2.500;
		
		hodnoty[2][0] = 10.0;
		hodnoty[2][1] = 40.0;
		hodnoty[2][2] = 1.000;
		hodnoty[2][3] = 0.2500;
		hodnoty[2][4] = 8.000;
		
		hodnoty[3][0] = 6.0;
		hodnoty[3][1] = 4.0;
		hodnoty[3][2] = 1.666;
		hodnoty[3][3] = 2.500;
		hodnoty[3][4] = 2.400;
		
		hodnoty[4][0] = 4.0;
		hodnoty[4][1] = 8.0;
		hodnoty[4][2] = 2.500;
		hodnoty[4][3] = 1.250;
		hodnoty[4][4] = 2.666;

		hodnoty[5][0] = 1.0;
		hodnoty[5][1] = 4.0;
		hodnoty[5][2] = 10.000;
		hodnoty[5][3] = 2.500;
		hodnoty[5][4] = 0.800;
		
		hodnoty[6][0] = 20.0;
		hodnoty[6][1] = 20.0;
		hodnoty[6][2] = 0.500;
		hodnoty[6][3] = 0.500;
		hodnoty[6][4] = 10.000;
		
		hodnoty[7][0] = 5.0;
		hodnoty[7][1] = 20.0;
		hodnoty[7][2] = 2.000;
		hodnoty[7][3] = 0.500;
		hodnoty[7][4] = 4.000;
		
		hodnoty[8][0] = 4.0;
		hodnoty[8][1] = 6.0;
		hodnoty[8][2] = 2.500;
		hodnoty[8][3] = 1.666;
		hodnoty[8][4] = 2.400;
		
		hodnoty[9][0] = 8.0;
		hodnoty[9][1] = 12.0;
		hodnoty[9][2] = 1.250;
		hodnoty[9][3] = 0.833;
		hodnoty[9][4] = 4.800;
		
		hodnoty[10][0] = 40.0;
		hodnoty[10][1] = 10.0;
		hodnoty[10][2] = 0.250;
		hodnoty[10][3] = 1.000;
		hodnoty[10][4] = 8.000;
		
		hodnoty[11][0] = 15.0;
		hodnoty[11][1] = 5.0;
		hodnoty[11][2] = 0.666;
		hodnoty[11][3] = 2.000;
		hodnoty[11][4] = 3.750;
		
		FitnessEvaluatorExampleRegression fitness = new FitnessEvaluatorExampleRegression();
		fitness.addValueVector(hodnoty);
		fitness.registerParameters(R1, R2, I1, I2);
		
		Config cfg = new Config("config_default.ini");
		IEvolutionSpecifier s = new DefaultEvolutionSpecifierTree(cfg, fitness, g);
		GProgram gp = new GProgram(cfg, s);

		gp.evolve();

		TreeChromozome ch = (TreeChromozome)gp.getPopulation().getBestIndividual();
		ch.visualize("chromozome.gif", DisplayType.BRIEF);

		System.out.println("Fitness: " + ch.getCachedFitness());
		System.out.println();
		//System.out.println(((TreeChromozome)ch).generateCode());
		
		System.out.println(ch.getCodeToVisualizer());
		
	}
}
